home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / language / sozobon2.zoo / libfp / fpadd.s < prev    next >
Text File  |  1990-12-16  |  4KB  |  159 lines

  1. * Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2. *
  3. * Permission is granted to anyone to use this software for any purpose
  4. * on any computer system, and to redistribute it freely, with the
  5. * following restrictions:
  6. * 1) No charge may be made other than reasonable charges for reproduction.
  7. * 2) Modified versions must be clearly marked as such.
  8. * 3) The authors are not responsible for any harmful consequences
  9. *    of using this software, even if they result from defects in it.
  10. *
  11. *
  12. * MODIFICATIONS:
  13. *
  14. * D.W.Brooks    Mar 89    Implemented rounding, inlined one-call subroutines,
  15. *            and several other speedups
  16. *
  17. * Rounding in the ambiguous case (tail byte = 0x80) uses round-to-even, as
  18. * Knuth insists (TAOCP3SNA).
  19. *
  20. *    fpsub
  21. *
  22.     .globl    fpsub
  23.     .globl    _fpsub
  24. fpsub:
  25. _fpsub:
  26.     eor.b    #$80,11(sp)    * negate B, fall through (can produce -0.0)
  27. *
  28. *    fpadd
  29. *
  30.     .globl    fpadd
  31.     .globl    _fpadd
  32. fpadd:
  33. _fpadd:
  34.     move.l    d3,a1        * save d3
  35.     move.l    d4,a2        * and d4
  36.     move.l    4(sp),d0    * First arg
  37.     move.l    8(sp),d1    * Second arg
  38.     move.l    d0,d4        * Keeps the result's sign
  39.     moveq.l    #$7f,d3
  40.  
  41.     move.b    d0,d2        * Compare signs only
  42.     eor.b    d1,d2
  43.     bpl    same_sign
  44. * different signs
  45.     and.b    d3,d0        * Force positive
  46.     and.b    d3,d1
  47.  
  48.     move.l    d0,d2        * note d2 is copy of d0
  49.     cmp.b    d0,d1        * Compare magnitudes
  50.     bne    sk1
  51.     cmp.l    d0,d1
  52. sk1:
  53.     ble    norev1
  54.     move.l    d1,d0        * swap d0/d1...d0 was saved in d2...
  55.     move.l    d2,d1
  56.     move.b    d0,d2        * ...now d2.b is copy of new d0.b
  57.     not.b    d4        * Invert sign
  58. norev1:
  59. * Begin unsigned subtract. Here we have (d0-d1), d0 >= d1, both positive.
  60. * d2.b has result exp.  Subtract 0.0 works without needing a special case.
  61.  
  62.     move.b    d0,d3
  63.     sub.b    d1,d3        * diff of exps (in low byte)
  64.  
  65.     clr.b    d0        * Extract mantissas
  66.     clr.b    d1
  67.  
  68.     cmp.b    #25,d3
  69.     bgt    out        * Nonsignificant addend: d0 is correct mantissa
  70.     lsr.l    d3,d1        * Shift uses d3 mod 64
  71.     sub.l    d1,d0
  72.  
  73.     beq    out0        * Zero: all done!
  74.     bmi    outsub        * Already normalized
  75. * normalize loop
  76. nloop:
  77.     subq.b    #1,d2
  78.     ble    underfl
  79.     add.l    d0,d0
  80.     bpl    nloop
  81.  
  82. outsub:
  83.     add.l    #$80,d0        * Force a rounding step.  This can't overflow.
  84.                 * (rum-ti-rum...can it?)
  85. *
  86. * Common exit point for checking rounding after adding 0x80.  If the tail
  87. * was not 0x80, it's already the correct result.  Otherwise, the tail is now
  88. * 0, and we implement the round-to-even.
  89. *
  90. outround:
  91.     tst.b    d0
  92.     bne    out
  93.     and.w    #$FE00,d0
  94. *
  95. * Common exit point.  d0 has the mantissa, d2 the exponent and d4 the sign.
  96. *
  97. out:
  98.     move.b    d2,d0
  99.     and.b    #$80,d4
  100.     or.b    d4,d0        * fix sign
  101. *
  102. * Come here when d0 has the result
  103. *
  104. out0:
  105.     move.l    a1,d3        * restore
  106.     move.l    a2,d4
  107.     rts
  108.  
  109. * underflow
  110. underfl:
  111.     moveq.l    #0,d0
  112.     bra    out0
  113. *
  114. * same signs: do add.
  115. *
  116. same_sign:
  117.     and.b    d3,d0        * Force both positive
  118.     and.b    d3,d1
  119.  
  120.     move.l    d0,d2
  121.     cmp.b    d0,d1        * Compare magnitudes
  122.     bne    sk2
  123.     cmp.l    d0,d1
  124. sk2:
  125.     ble    norev2
  126.     move.l    d1,d0        * Swap d0/d1...
  127.     move.l    d2,d1
  128.     move.b    d0,d2        * ...and d2.b is a copy of d0.b
  129. norev2:
  130. * Begin unsigned add: (d0+d1), d0 >= d1
  131.     sub.b    d1,d0
  132.     move.b    d0,d3        * diff of exps
  133.  
  134.     clr.b    d0        * Extract mantissas
  135.     clr.b    d1
  136.  
  137.     cmp.b    #25,d3
  138.     bge    out        * Nonsignificant addend: d0 has result mantissa
  139.     lsr.l    d3,d1
  140.     add.l    d1,d0
  141.     bcc    around
  142.     roxr.l    #1,d0        * Mantissa overflowed the word
  143.     addq.b    #1,d2
  144.     bmi    oflo        * Exponent too hot to handle
  145.  
  146. around:                * Round the fraction.
  147.     add.l    #$80,d0        * This rounds unless d0.b was 0x80
  148.     bcc    outround    * No overflow, but do final rounding
  149.     roxr.l    #1,d0        * Actually loads 0x800000nn
  150.     addq.b    #1,d2        * Compensate
  151.     bpl    out        * Ok if no exponent overflow
  152.  
  153. oflo:
  154.     moveq.l    #$ffffffff,d0    * Handle exponent overflow, maintaining sign
  155.     moveq.l    #$7f,d2
  156.     bra    out
  157.  
  158.     .end
  159.